﻿//-------------------------------------------------------------------
//	Copyright (c) 2010-2014  Zhirnov Andrey
//	This file is part of the "UX Standard Lib" project.
//	See copyright notice in "UX_STL_Core.h".
//-------------------------------------------------------------------

#ifndef _UXS_SINGLETON_H
#define _UXS_SINGLETON_H

#pragma once

#include "../OS/OSLowLevel.h"

namespace UX_STL
{
namespace UXTypes
{

	//
	// Singleton for multi threading
	//

	struct SingletonMultiThread
	{
	protected:
		static Mutex		_sCS;

		template <typename T>
		static T & _Instance()
		{
			static T	t;
			return t;
		}


	public:
		template <typename T>
		static T * Instance()
		{
			static T * volatile	ptr;

			if ( ptr == null )
			{
				T *	temp = null;
				{
					SCOPELOCK( _sCS );
					temp = & _Instance<T>();
				}
				ptr = temp;
			}
			return ptr;
		}
	};



	//
	// Singleton for one thread
	//

	template <typename T>
	struct TSingletonLocalConstructor
	{
		static T *&	Get(T *&ptr)			{ return ( ptr != null ? ptr : (ptr = new T()) ); }
		static void Set(T *&ptr, T *newPtr)	{ if (ptr != null) { delete ptr; }  ptr = newPtr; }
	};


	struct SingletonLocal
	{
	protected:
		template <typename T>
		static T *& _Instance()
		{
			static UX_THREAD_LOCAL T *	t = null;
			return t;
		}


	public:
		template <typename T>
		static T * Instance()
		{
			typedef TSingletonLocalConstructor<T>	Strategy;
			return Strategy::Get( _Instance<T>() );
		}

		template <typename T>
		static void SetInstance(T *ptr)
		{
			typedef TSingletonLocalConstructor<T>	Strategy;
			Strategy::Set( _Instance<T>(), ptr );
		}
	};



	//
	// Singleton for single thread
	//

	struct SingletonSingleThread
	{
	public:
		template <typename T>
		static T * Instance()
		{
			static T	t;
			return &t;
		}
	};


	typedef SingletonMultiThread	Singleton;

//-------------------------------------------------------------------

}	// UXTypes
}	// UX_STL

#endif	// _UXS_SINGLETON_H